package cn.cas.mango.util.RequestUtil;

import cn.cas.mango.dto.param.hot.HotSpotParam;
import cn.cas.mango.service.ConfigService;
import co.elastic.clients.elasticsearch.ElasticsearchClient;
import co.elastic.clients.elasticsearch._types.FieldValue;
import co.elastic.clients.elasticsearch._types.query_dsl.BoolQuery;
import co.elastic.clients.elasticsearch._types.query_dsl.MatchQuery;
import co.elastic.clients.elasticsearch._types.query_dsl.QueryBuilders;
import co.elastic.clients.elasticsearch._types.query_dsl.RangeQuery;
import co.elastic.clients.elasticsearch._types.query_dsl.TermQuery;
import co.elastic.clients.elasticsearch._types.query_dsl.TermsQuery;
import co.elastic.clients.elasticsearch.core.CountRequest;
import co.elastic.clients.elasticsearch.core.SearchRequest;
import co.elastic.clients.json.JsonData;
import org.apache.logging.log4j.util.Strings;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.Map;

@Service
public class BuildHotSpotRequest {
  @Autowired
  private ConfigService config;
  @Autowired
  private ElasticsearchClient client;
  public final String[] includesArray = new String[]{
//      "fssj", "keywords",
//      "lyss", "nm", "zlnm", "sjmc",
//      "sjms", "ssly", "entities", "entities_organization", "entities_place", "drsj"
  };

  private void setNormal(SearchRequest.Builder builder, HotSpotParam queryParam,
                         String queryStr, RangeQuery rq, BoolQuery tempBoolQuery, List<String> includes) {
    setNormalItem(builder, queryParam, queryStr, rq, tempBoolQuery, includes);
        builder
        .from((queryParam.getCurrentPage() - 1) * queryParam.getPageSize())
        .size(queryParam.getPageSize())
        .trackTotalHits(c -> c.count(config.getHitsCount()))
        .source(source -> source.filter(f -> f.includes(includes)));
  }

  private void setNormalItem(SearchRequest.Builder builder, HotSpotParam queryParam,
                             String queryStr, RangeQuery rq, BoolQuery tempBoolQuery, List<String> includes) {
    builder
        .index(config.getHotspotIndex())
        .query(QueryBuilders.bool(bool ->
            {
              BoolQuery.Builder b;

              if (Strings.isBlank(queryStr)) {
                if (rq != null) {
                  b = bool.filter(f -> f.range(rq));
                } else {
                  b = bool;
                }
              } else {
                if (rq != null) {
                  b = bool.must(must -> must.bool(tempBoolQuery))
                      .filter(f -> f.range(rq));
                } else {
                  b = bool.must(must -> must.bool(tempBoolQuery))
                  ;
                }
              }
              List<FieldValue> provinceArray = queryParam.getProvinceArray();

              if (provinceArray != null && !provinceArray.isEmpty()) {
                TermsQuery sq1 = TermsQuery.of(
                    t -> t.field("lyss").terms(x -> x.value(provinceArray)));
                b = b.filter(f -> f.terms(sq1));
              }

              // 删除province是中美和海外的
              List<FieldValue> excludesProvince = getExclusiveProvince();

              TermsQuery excludesQuery = TermsQuery.of(
                  t -> t.field("lyss").terms(x -> x.value(excludesProvince)));
              b = b.mustNot(mustNot -> mustNot.terms(excludesQuery));

              String area = queryParam.getSsly();
              if (!Strings.isBlank(area)) {
                Map<String, String> number2AreaCast = config.getNumber2AreaCast();
                area = number2AreaCast.get(area);
                String finalArea = area;
                TermQuery sq1 = TermQuery.of(
                    t->t.field("ssly").value(finalArea)
                );
                b = b.filter(f->f.term(sq1));
              }
              return b;
            }
        ));
  }
  private void setNormalItem(CountRequest.Builder builder, HotSpotParam queryParam,
                             String queryStr, RangeQuery rq, BoolQuery tempBoolQuery, List<String> includes) {
    builder
        .index(config.getHotspotIndex())
        .query(QueryBuilders.bool(bool ->
            {
              BoolQuery.Builder b;

              if (Strings.isBlank(queryStr)) {
                if (rq != null) {
                  b = bool.filter(f -> f.range(rq));
                } else {
                  b = bool;
                }
              } else {
                if (rq != null) {
                  b = bool.must(must -> must.bool(tempBoolQuery))
                      .filter(f -> f.range(rq));
                } else {
                  b = bool.must(must -> must.bool(tempBoolQuery))
                  ;
                }
              }
              List<FieldValue> provinceArray = queryParam.getProvinceArray();

              if (provinceArray != null && !provinceArray.isEmpty() && !provinceArray.contains("全部")) {
                TermsQuery sq1 = TermsQuery.of(
                    t -> t.field("lyss").terms(x -> x.value(provinceArray)));
                b = b.filter(f -> f.terms(sq1));
              }

              // 删除province是中美和海外的
              List<FieldValue> excludesProvince = getExclusiveProvince();

              TermsQuery excludesQuery = TermsQuery.of(
                  t -> t.field("lyss").terms(x -> x.value(excludesProvince)));
              b = b.mustNot(mustNot -> mustNot.terms(excludesQuery));

              String area = queryParam.getSsly();
              if (!Strings.isBlank(area)) {
                Map<String, String> number2AreaCast = config.getNumber2AreaCast();
                area = number2AreaCast.get(area);
                String finalArea = area;
                TermQuery sq1 = TermQuery.of(
                    t->t.field("ssly").value(finalArea)
                );
                b = b.filter(f->f.term(sq1));
              }
              return b;
            }
        ));
  }

  /**
   *
   * @param queryParam, 包含startDate和endDate
   * @return 该时间段内所有的除中美以外的文件数量
   */
  public CountRequest.Builder getDateTotalNum(HotSpotParam queryParam) {
    List<String> fields = new ArrayList<>();
    String queryField = "sjmc";
    fields.add(queryField);
    String queryStr = queryParam.getQuery().trim();
    String[] splitQueryStr = queryStr.split("\\s+");
    MatchQuery matchQuery = null;
    BoolQuery.Builder tempBool = new BoolQuery.Builder();
    for (String query: splitQueryStr) {
      matchQuery = MatchQuery.of(v -> v.query(query).field(fields.get(0)));
      MatchQuery finalMatchQuery = matchQuery;
      tempBool.must(m->m.match(finalMatchQuery));
    }
    RangeQuery rq = wrapRangeQuery(queryParam);
    BoolQuery tempBoolQuery = tempBool.build();
    CountRequest.Builder builder = new CountRequest.Builder();
    setNormalItem(builder, queryParam, queryStr, rq, tempBoolQuery, Arrays.asList(includesArray));
    return builder;
  }


  private RangeQuery wrapRangeQuery(HotSpotParam queryParam) {
    RangeQuery rq;
    if (Strings.isNotBlank(queryParam.getStartDate()) && Strings.isNotBlank(
        queryParam.getEndDate())) {
      rq = RangeQuery.of(
          r -> r.field("fssj").gte(JsonData.of(queryParam.getStartDate()))
              .lte(JsonData.of(queryParam.getEndDate())));
    } else if (Strings.isNotBlank(queryParam.getStartDate())) {
      rq = RangeQuery.of(
          r -> r.field("fssj").gte(JsonData.of(queryParam.getStartDate())));
    } else if (Strings.isNotBlank(queryParam.getEndDate())) {
      rq = RangeQuery.of(
          r -> r.field("fssj").lte(JsonData.of(queryParam.getEndDate())));
    } else {
      rq = null;
    }
    return rq;
  }
  // 这里lyss为 中美、海外 不参与计算
  public SearchRequest.Builder buildRequest(HotSpotParam queryParam) {
    List<String> fields = new ArrayList<>();
    String queryField = "sjmc";
    fields.add(queryField);
    String queryStr = queryParam.getQuery().trim();
    String[] splitQueryStr = queryStr.split("\\s+");
    MatchQuery matchQuery = null;
    BoolQuery.Builder tempBool = new BoolQuery.Builder();
    for (String query: splitQueryStr) {
      matchQuery = MatchQuery.of(v -> v.query(query).field(fields.get(0)));
      MatchQuery finalMatchQuery = matchQuery;
      tempBool.must(m->m.match(finalMatchQuery));
    }
    RangeQuery rq = wrapRangeQuery(queryParam);
    BoolQuery tempBoolQuery = tempBool.build();
    SearchRequest.Builder builder = new SearchRequest.Builder();
    setNormal(builder, queryParam, queryStr, rq, tempBoolQuery, Arrays.asList(includesArray));
    return builder;
  }

  public List<FieldValue> getExclusiveProvince() {
    List<FieldValue> excludesProvince = new ArrayList<>();
    excludesProvince.add(FieldValue.of("中美"));
    excludesProvince.add(FieldValue.of("海外"));
    return excludesProvince;
  }
}
